﻿using System;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Globalization;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Controls.Primitives;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;

namespace Gmantis.Controls.Extended
{
    public enum DatePickerFormat
    {
        Long,
        Short,
        Custom
    }

    [TemplateVisualState(Name = "Normal", GroupName = "CommonStates"), 
    StyleTypedProperty(Property = "ValidationDecoratorStyle", StyleTargetType = typeof(ValidationDecorator)), 
    TemplatePart(Name = "TextBox", Type = typeof(TextBoxBase)), TemplateVisualState(Name = "InvalidFocused", GroupName = "ValidationStatesStates"), 
    TemplatePart(Name = "Button", Type = typeof(Button)), TemplateVisualState(Name = "InvalidUnfocused", GroupName = "ValidationStatesStates"), 
    TemplateVisualState(Name = "MouseOver", GroupName = "CommonStates"), TemplateVisualState(Name = "Disabled", GroupName = "CommonStates"), 
    TemplatePart(Name = "Root", Type = typeof(FrameworkElement)), StyleTypedProperty(Property = "CalendarStyle", StyleTargetType = typeof(System.Windows.Controls.Calendar)), 
    TemplatePart(Name = "Popup", Type = typeof(Popup)), TemplateVisualState(Name = "Focused", GroupName = "FocusStates"), 
    TemplateVisualState(Name = "Unfocused", GroupName = "FocusStates"), TemplateVisualState(Name = "Valid", GroupName = "ValidationStatesStates")]
    public class DatePicker : Control
    {
        // Fields
        private System.Windows.Controls.Calendar _calendar;
        private bool _changed;
        private string _defaultText;
        internal Button _elementButton;
        internal Popup _elementPopup;
        internal FrameworkElement _elementRoot;
        internal TextBoxBase _elementTextBox;
        internal bool _isLoaded;
        private MaskedTextBox _maskedBox;
        private DateTime? _onOpenSelectedDate;
        private Canvas _outsideCanvas;
        private Canvas _outsidePopupCanvas;
        private bool _settingSelectedDate;
        private bool _throwIsMouseOverChanged;
        private bool _typing;
        public static readonly DependencyProperty AllowNullProperty = DependencyProperty.Register("AllowNull", typeof(bool), typeof(DatePicker), new PropertyMetadata(false, new PropertyChangedCallback(DatePicker.OnAllowNullPropertyChanged)));
        public static readonly DependencyProperty ButtonBackgroundProperty = DependencyProperty.Register("ButtonBackground", typeof(Brush), typeof(DatePicker), null);
        internal const string ButtonElementName = "Button";
        public static readonly DependencyProperty ButtonForegroundProperty = DependencyProperty.Register("ButtonForeground", typeof(Brush), typeof(DatePicker), null);
        public static readonly DependencyProperty CalendarStyleProperty = DependencyProperty.Register("CalendarStyle", typeof(Style), typeof(DatePicker), new PropertyMetadata(new PropertyChangedCallback(DatePicker.OnCalendarStylePropertyChanged)));
        public static readonly DependencyProperty CaretBrushProperty = DependencyProperty.Register("CaretBrush", typeof(Brush), typeof(DatePicker), null);
        public static readonly DependencyProperty CornerRadiusProperty = DependencyProperty.Register("CornerRadius", typeof(CornerRadius), typeof(DatePicker), null);
        public static readonly DependencyProperty CustomFormatProperty = DependencyProperty.Register("CustomFormat", typeof(string), typeof(DatePicker), new PropertyMetadata(new PropertyChangedCallback(DatePicker.OnCustomFormatPropertyChanged)));
        public static readonly DependencyProperty DisabledCuesVisibilityProperty = DependencyProperty.Register("DisabledCuesVisibility", typeof(Visibility), typeof(DatePicker), new PropertyMetadata(Visibility.Visible));
        public static readonly DependencyProperty DisplayDateEndProperty = DependencyProperty.Register("DisplayDateEnd", typeof(DateTime?), typeof(DatePicker), new PropertyMetadata(null, new PropertyChangedCallback(DatePicker.OnDisplayDateEndChanged)));
        public static readonly DependencyProperty DisplayDateProperty = DependencyProperty.Register("DisplayDate", typeof(DateTime), typeof(DatePicker), new PropertyMetadata(DateTime.Today, new PropertyChangedCallback(DatePicker.OnDisplayDateChanged)));
        public static readonly DependencyProperty DisplayDateStartProperty = DependencyProperty.Register("DisplayDateStart", typeof(DateTime?), typeof(DatePicker), new PropertyMetadata(null, new PropertyChangedCallback(DatePicker.OnDisplayDateStartChanged)));
        public static readonly DependencyProperty FirstDayOfWeekProperty = DependencyProperty.Register("FirstDayOfWeek", typeof(DayOfWeek), typeof(DatePicker), new PropertyMetadata(DayOfWeek.Sunday, new PropertyChangedCallback(DatePicker.OnFirstDayOfWeekPropertyChanged)));
        public static readonly DependencyProperty FocusBrushProperty = DependencyProperty.Register("FocusBrush", typeof(Brush), typeof(DatePicker), null);
        public static readonly DependencyProperty FocusCuesVisibilityProperty = DependencyProperty.Register("FocusCuesVisibility", typeof(Visibility), typeof(DatePicker), new PropertyMetadata(Visibility.Visible));
        internal static readonly DependencyProperty ForceMouseOverProperty = DependencyProperty.Register("ForceMouseOver", typeof(bool), typeof(DatePicker), new PropertyMetadata(new PropertyChangedCallback(DatePicker.OnForceMouseOverPropertyChanged)));
        public static readonly DependencyProperty IsDropDownOpenProperty = DependencyProperty.Register("IsDropDownOpen", typeof(bool), typeof(DatePicker), new PropertyMetadata(false, new PropertyChangedCallback(DatePicker.OnIsDropDownOpenPropertyChanged)));
        public static readonly DependencyProperty IsFocusedProperty = DependencyProperty.Register("IsFocused", typeof(bool), typeof(DatePicker), new PropertyMetadata(new PropertyChangedCallback(DatePicker.OnIsFocusedPropertyChanged)));
        public static readonly DependencyProperty IsMouseOverProperty = DependencyProperty.Register("IsMouseOver", typeof(bool), typeof(DatePicker), new PropertyMetadata(new PropertyChangedCallback(DatePicker.OnIsMouseOverPropertyChanged)));
        public static readonly DependencyProperty IsReadOnlyProperty = DependencyProperty.Register("IsReadOnly", typeof(bool), typeof(DatePicker), new PropertyMetadata(new PropertyChangedCallback(DatePicker.OnIsReadOnlyPropertyChanged)));
        public static readonly DependencyProperty IsTodayHighlightedProperty = DependencyProperty.Register("IsTodayHighlighted", typeof(bool), typeof(DatePicker), new PropertyMetadata(true, new PropertyChangedCallback(DatePicker.OnIsTodayHighlightedPropertyChanged)));
        public static readonly DependencyProperty MaskProperty = DependencyProperty.Register("Mask", typeof(string), typeof(DatePicker), new PropertyMetadata(string.Empty, new PropertyChangedCallback(DatePicker.OnMaskPropertyChanged)));
        public static readonly DependencyProperty MouseOverBrushProperty = DependencyProperty.Register("MouseOverBrush", typeof(Brush), typeof(DatePicker), null);
        internal const string PopupElementName = "Popup";
        public static readonly DependencyProperty PressedBrushProperty = DependencyProperty.Register("PressedBrush", typeof(Brush), typeof(DatePicker), null);
        public static readonly DependencyProperty PromptProperty = DependencyProperty.Register("Prompt", typeof(string), typeof(DatePicker), new PropertyMetadata("_", new PropertyChangedCallback(DatePicker.OnPromptPropertyChanged)));
        internal const string RootElementName = "Root";
        public static readonly DependencyProperty SelectedDateFormatProperty = DependencyProperty.Register("SelectedDateFormat", typeof(DatePickerFormat), typeof(DatePicker), new PropertyMetadata(DatePickerFormat.Short, new PropertyChangedCallback(DatePicker.OnSelectedDateFormatPropertyChanged)));
        public static readonly DependencyProperty SelectedDateProperty = DependencyProperty.Register("SelectedDate", typeof(DateTime?), typeof(DatePicker), new PropertyMetadata(null, new PropertyChangedCallback(DatePicker.OnSelectedDateChanged)));
        public static readonly DependencyProperty SelectionBackgroundProperty = DependencyProperty.Register("SelectionBackground", typeof(Brush), typeof(DatePicker), null);
        public static readonly DependencyProperty SelectionForegroundProperty = DependencyProperty.Register("SelectionForeground", typeof(Brush), typeof(DatePicker), null);
        internal const string TextBoxElementName = "TextBox";
        public static readonly DependencyProperty TextProperty = DependencyProperty.Register("Text", typeof(string), typeof(DatePicker), new PropertyMetadata(string.Empty, new PropertyChangedCallback(DatePicker.OnTextPropertyChanged)));
        public static readonly DependencyProperty ValidationDecoratorStyleProperty = DependencyProperty.Register("ValidationDecoratorStyle", typeof(Style), typeof(DatePicker), null);
        public static readonly DependencyProperty WatermarkProperty = DependencyProperty.Register("Watermark", typeof(object), typeof(DatePicker), new PropertyMetadata(new PropertyChangedCallback(DatePicker.OnWatermarkPropertyChanged)));

        // Events
        public event RoutedEventHandler CalendarClosed;
        public event RoutedEventHandler CalendarOpened;
        public event EventHandler<DatePickerDateValidationErrorEventArgs> DateValidationError;
        public event EventHandler<PropertyChangedEventArgs<bool>> IsMouseOverChanged;
        public event SelectionChangedEventHandler SelectedDateChanged;
        public event EventHandler<PropertyChangedEventArgs<object>> SelectionCommitted;

        // Methods
        public DatePicker()
        {
            RoutedEventHandler handler = null;
            this._throwIsMouseOverChanged = true;
            this._defaultText = string.Empty;
            base.DefaultStyleKey = typeof(DatePicker);
            if (handler == null)
            {
                handler = (param0, param1) => this.ChangeVisualStateFocus(false);
            }
            base.Loaded += handler;
            base.GotFocus += new RoutedEventHandler(this.Control_GotFocus);
            base.LostFocus += new RoutedEventHandler(this.Control_LostFocus);
            this.SetCustomDefaultValues();
        }

        private void Control_GotFocus(object sender, RoutedEventArgs e)
        {
            this.IsFocused = true;
        }

        private void Control_LostFocus(object sender, RoutedEventArgs e)
        {
            this.IsFocused = false;
        }

        private void Control_MouseEnter(object sender, MouseEventArgs e)
        {
            this.IsMouseOver = true;
        }

        private void Control_MouseLeave(object sender, MouseEventArgs e)
        {
            this.IsMouseOver = false;
        }

        private void Calendar_DisplayDateChanged(object sender, CalendarDateChangedEventArgs e)
        {
            if (e.AddedDate != this.DisplayDate)
            {
                base.SetValue(DisplayDateProperty, e.AddedDate.Value);
            }
        }

        private void Calendar_KeyDown(object sender, System.Windows.Input.KeyEventArgs e)
        {
            System.Windows.Controls.Calendar calendar = sender as System.Windows.Controls.Calendar;
            if ((((e.Key == Key.Enter) || (e.Key == Key.Space)) || (e.Key == Key.Escape)) && (calendar.DisplayMode == CalendarMode.Month))
            {
                if (e.Key == Key.Escape)
                {
                    this._changed = false;
                }
                this.ClosePopUp();
                if (e.Key == Key.Escape)
                {
                    this.SelectedDate = this._onOpenSelectedDate;
                }
            }
        }

        private void Calendar_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
        {
            e.Handled = true;
        }

        private void Calendar_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
        {
            if (e.Handled)
            {
                CalendarDayButton originalSource = e.OriginalSource as CalendarDayButton;
                if (originalSource == null)
                {
                    originalSource = VTreeHelper.GetParentOfType(e.OriginalSource as DependencyObject, typeof(CalendarDayButton)) as CalendarDayButton;
                }
                if (originalSource != null)
                {
                    this.ClosePopUp();
                }
            }
        }

        private void Calendar_SelectedDatesChanged(object sender, System.Windows.Controls.SelectionChangedEventArgs e)
        {
            if (((e.AddedItems.Count > 0) && this.SelectedDate.HasValue) && (DateTime.Compare((DateTime)e.AddedItems[0], this.SelectedDate.Value) != 0))
            {
                this.SelectedDate = (DateTime?)e.AddedItems[0];
            }
            else if (e.AddedItems.Count == 0)
            {
                this.SelectedDate = null;
            }
            else if (!this.SelectedDate.HasValue && (e.AddedItems.Count > 0))
            {
                this.SelectedDate = (DateTime?)e.AddedItems[0];
            }
        }

        private void Calendar_SizeChanged(object sender, SizeChangedEventArgs e)
        {
            this.SetPopUpPosition();
        }

        protected void ChangeVisualStateCommon(bool useTransitions)
        {
            if (base.IsEnabled)
            {
                VisualStateHelper.GoToState(this, "MouseOver", useTransitions);
            }
            if (!base.IsEnabled)
            {
                VisualStateHelper.GoToState(this, "Disabled", useTransitions);
            }
            if ((base.IsEnabled && !this.IsMouseOver) && !this.ForceMouseOver)
            {
                VisualStateHelper.GoToState(this, "Normal", useTransitions);
            }
        }

        protected void ChangeVisualStateFocus(bool useTransitions)
        {
            if (!this.IsFocused)
            {
                VisualStateHelper.GoToState(this, "Unfocused", useTransitions);
            }
            if (this.IsFocused)
            {
                VisualStateHelper.GoToState(this, "Focused", useTransitions);
            }
        }

        private void ClosePopUp()
        {
            if (this.IsDropDownOpen)
            {
                base.Focus();
                this._calendar.ReleaseMouseCapture();
                this.IsDropDownOpen = false;
            }
        }

        private string DateTimeToString(DateTime d)
        {
            DateTimeFormatInfo currentDateTimeFormat = TimeEditor.GetCurrentDateTimeFormat(this);
            switch (this.SelectedDateFormat)
            {
                case DatePickerFormat.Long:
                    return string.Format(CultureInfo.CurrentCulture, d.ToString(currentDateTimeFormat.LongDatePattern, currentDateTimeFormat), new object[0]);

                case DatePickerFormat.Short:
                    return string.Format(CultureInfo.CurrentCulture, d.ToString(currentDateTimeFormat.ShortDatePattern, currentDateTimeFormat), new object[0]);

                case DatePickerFormat.Custom:
                    try
                    {
                        return d.ToString(this.CustomFormat, CultureInfo.CurrentCulture);
                    }
                    catch (FormatException)
                    {
                    }
                    break;
            }
            return null;
        }

        private void ElementText_KeyDown(object sender, System.Windows.Input.KeyEventArgs e)
        {
            if (!e.Handled)
            {
                Key key = e.Key;
                if (key != Key.Enter)
                {
                    if (key != Key.Down)
                    {
                        return;
                    }
                }
                else
                {
                    this.SetSelectedDate();
                    e.Handled = true;
                    return;
                }
                if ((Keyboard.Modifiers & ModifierKeys.Control) == ModifierKeys.Control)
                {
                    this.TogglePopUp();
                    e.Handled = true;
                }
            }
        }

        private void ElementText_TextChanged(object sender, TextChangedEventArgs e)
        {
            if (this._elementTextBox != null)
            {
                if ((!this.IsReadOnly && !string.IsNullOrEmpty(this._elementTextBox.Text)) && !this._elementTextBox.IsWatermarked)
                {
                    VisualStateHelper.GoToState(this._elementTextBox, "Unwatermarked", false);
                }
                try
                {
                    this._typing = true;
                    base.SetValue(TextProperty, this._elementTextBox.Text);
                }
                finally
                {
                    this._typing = false;
                }
            }
        }

        public void FinalizeEditing()
        {
            if (this._elementTextBox != null)
            {
                this.Text = this._elementTextBox.Text;
                if (this.AllowNull && string.IsNullOrEmpty(this.Text))
                {
                    this.SelectedDate = null;
                }
                this.SetSelectedDate();
            }
        }

        private T GetTemplateChild<T>(string childName, bool required, ref string errors) where T : class
        {
            DependencyObject templateChild = base.GetTemplateChild(childName);
            ApplyTemplateHelper.VerifyTemplateChild(typeof(T), "template part", childName, templateChild, required, ref errors);
            return (templateChild as T);
        }

        private static Storyboard GetTemplateChildResource(FrameworkElement root, string resourceName, bool required, ref string errors)
        {
            return GetTemplateChildResource<Storyboard>(root, resourceName, required, ref errors);
        }

        private static T GetTemplateChildResource<T>(FrameworkElement root, string resourceName, bool required, ref string errors) where T : class
        {
            object child = root.Resources[resourceName];
            ApplyTemplateHelper.VerifyTemplateChild(typeof(T), "resource", resourceName, child, required, ref errors);
            return (child as T);
        }

        private void HandleIsReadOnlyProperty()
        {
            if (this._isLoaded)
            {
                if (this._elementButton != null)
                {
                    this._elementButton.IsEnabled = !this.IsReadOnly;
                }
                this._elementTextBox.IsReadOnly = this.IsReadOnly;
            }
        }

        private void InitializeButtonPart()
        {
            RoutedEventHandler handler = null;
            if (this._elementButton != null)
            {
                if (handler == null)
                {
                    handler = (param0, param1) => this.TogglePopUp();
                }
                this._elementButton.Click += handler;
                this._elementButton.IsTabStop = false;
                if (this._elementButton.Content == null)
                {
                    this._elementButton.Content = "Show Calendar";
                }
            }
        }

        private void InitializeCalendar()
        {
            this._calendar = new System.Windows.Controls.Calendar();
            this._calendar.DisplayDateChanged += new EventHandler<CalendarDateChangedEventArgs>(this.Calendar_DisplayDateChanged);
            this._calendar.SelectedDatesChanged += new EventHandler<System.Windows.Controls.SelectionChangedEventArgs>(this.Calendar_SelectedDatesChanged);
            this._calendar.MouseLeftButtonDown += new MouseButtonEventHandler(this.Calendar_MouseLeftButtonDown);
            this._calendar.AddHandler(UIElement.MouseLeftButtonUpEvent, new MouseButtonEventHandler(this.Calendar_MouseLeftButtonUp), true);
            this._calendar.SelectionMode = CalendarSelectionMode.SingleDate;
            this._calendar.AddHandler(UIElement.KeyDownEvent, new KeyEventHandler(this.Calendar_KeyDown), true);
            this._calendar.HorizontalAlignment = HorizontalAlignment.Left;
            this._calendar.VerticalAlignment = VerticalAlignment.Top;
            this._calendar.SizeChanged += new SizeChangedEventHandler(this.Calendar_SizeChanged);
            this._calendar.IsTabStop = true;
            this.BlackoutDates = this._calendar.BlackoutDates;
        }

        private void InitializePopupPart()
        {
            if (this._elementPopup != null)
            {
                if (this._outsideCanvas == null)
                {
                    this._outsideCanvas = new Canvas();
                    this._outsidePopupCanvas = new Canvas();
                    this._outsidePopupCanvas.Background = new SolidColorBrush(Colors.Transparent);
                    this._outsideCanvas.Children.Add(this._outsidePopupCanvas);
                    this._outsideCanvas.Children.Add(this._calendar);
                    this._outsidePopupCanvas.MouseLeftButtonDown += new MouseButtonEventHandler(this.OutsidePopupCanvas_MouseLeftButtonDown);
                }
                this._elementPopup.Child = this._outsideCanvas;
                this.OnIsDropDownOpenChanged(false);
            }
        }

        private void InitializeTextBoxPart()
        {
            RoutedEventHandler handler = null;
            RoutedEventHandler handler2 = null;
            this._maskedBox = this._elementTextBox as MaskedTextBox;
            if (this._elementTextBox != null)
            {
                this._elementTextBox.BindInputMethodProperties(this);
                this._elementTextBox.KeyDown += new KeyEventHandler(this.ElementText_KeyDown);
                this._elementTextBox.TextChanged += new TextChangedEventHandler(this.ElementText_TextChanged);
                if (!this.SelectedDate.HasValue)
                {
                    if (!string.IsNullOrEmpty(this._defaultText))
                    {
                        this._elementTextBox.Text = this._defaultText;
                        this.SetSelectedDate();
                    }
                }
                else
                {
                    this._elementTextBox.Text = this.DateTimeToString(this.SelectedDate.Value);
                }
                if (handler == null)
                {
                    handler = delegate(object param0, RoutedEventArgs param1)
                    {
                        this.ClosePopUp();
                        this.BeginInvoke(delegate
                        {
                            if (!string.IsNullOrEmpty(this._elementTextBox.Text))
                            {
                                this._elementTextBox.SelectionStart = 0;
                                this._elementTextBox.Select(0, this._elementTextBox.Text.Length);
                            }
                            VisualStateHelper.GoToState(this._elementTextBox, "Unwatermarked", false);
                            this._elementTextBox.Focus();
                        });
                    };
                }
                this._elementTextBox.GotFocus += handler;
                if (handler2 == null)
                {
                    handler2 = (param0, param1) => this.FinalizeEditing();
                }
                this._elementTextBox.LostFocus += handler2;
            }
        }

        private static bool InvertMatrix(ref Matrix matrix)
        {
            double num = (matrix.M11 * matrix.M22) - (matrix.M12 * matrix.M21);
            if (num == 0.0)
            {
                return false;
            }
            Matrix matrix2 = matrix;
            matrix.M11 = matrix2.M22 / num;
            matrix.M12 = (-1.0 * matrix2.M12) / num;
            matrix.M21 = (-1.0 * matrix2.M21) / num;
            matrix.M22 = matrix2.M11 / num;
            matrix.OffsetX = ((matrix2.OffsetY * matrix2.M21) - (matrix2.OffsetX * matrix2.M22)) / num;
            matrix.OffsetY = ((matrix2.OffsetX * matrix2.M12) - (matrix2.OffsetY * matrix2.M11)) / num;
            return true;
        }

        private bool IsEmpty()
        {
            if ((this._maskedBox == null) || string.IsNullOrEmpty(this._maskedBox.Mask))
            {
                return string.IsNullOrEmpty(this._elementTextBox.Text);
            }
            string str = this._maskedBox.Value;
            if (!string.IsNullOrEmpty(str))
            {
                foreach (char ch in str)
                {
                    if (ch != this.Prompt[0])
                    {
                        return false;
                    }
                }
            }
            return true;
        }

        private bool IsValidDateSelection(object value)
        {
            return ((value == null) || ((!this.BlackoutDates.Contains((DateTime)value) && (DateTime.Compare((DateTime)value, this.DisplayDateStart.GetValueOrDefault(DateTime.MinValue)) >= 0)) && (DateTime.Compare((DateTime)value, this.DisplayDateEnd.GetValueOrDefault(DateTime.MaxValue)) <= 0)));
        }

        private static bool IsValidSelectedDateFormat(DatePickerFormat value)
        {
            if ((value != DatePickerFormat.Long) && (value != DatePickerFormat.Short))
            {
                return (value == DatePickerFormat.Custom);
            }
            return true;
        }

        private void OnAfterApplyTemplate()
        {
            this.ChangeVisualStateCommon(false);
            this.HandleIsReadOnlyProperty();
            if (!this.SelectedDate.HasValue)
            {
                this.SetWaterMarkText();
            }
            this.OnMaskChanged(this.Mask);
            this.OnCustomFormatChangedImpl(this.CustomFormat);
            this.SetSelectedDate();
        }

        private void OnAllowNullChanged(bool oldValue)
        {
            if (!this.AllowNull && !this.SelectedDate.HasValue)
            {
                this.SetSelectedDate();
            }
        }

        private static void OnAllowNullPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            DatePicker picker = d as DatePicker;
            bool oldValue = (bool)e.OldValue;
            picker.OnAllowNullChanged(oldValue);
        }

        public override void OnApplyTemplate()
        {
            this.OnBeforeApplyTemplate();
            string errors = string.Empty;
            base.OnApplyTemplate();
            this._isLoaded = true;
            this._elementTextBox = this.GetTemplateChild<TextBoxBase>("TextBox", true, ref errors);
            if (this._elementTextBox != null)
            {
                this.InitializeTextBoxPart();
            }
            this._elementRoot = this.GetTemplateChild<FrameworkElement>("Root", false, ref errors);
            this._elementButton = this.GetTemplateChild<Button>("Button", false, ref errors);
            if (this._elementButton != null)
            {
                this.InitializeButtonPart();
            }
            this._elementPopup = this.GetTemplateChild<Popup>("Popup", false, ref errors);
            if (this._elementPopup != null)
            {
                this.InitializePopupPart();
            }
            if (!string.IsNullOrEmpty(errors))
            {
                this._isLoaded = false;
                if ((base.Template != null) && !PlatformIndependent.IsInDesignMode(this))
                {
                    throw new InvalidOperationException(string.Format(CultureInfo.InvariantCulture, "Template cannot be applied to DatePicker.\nDetails: {0}", new object[] { errors }));
                }
            }
            else
            {
                this.ChangeVisualStateFocus(false);
                this.OnAfterApplyTemplate();
            }
        }

        private void OnBeforeApplyTemplate()
        {
            if (this._elementPopup != null)
            {
                this._elementPopup.Child = null;
            }
            if (this._elementTextBox != null)
            {
                this._elementTextBox.KeyDown -= new KeyEventHandler(this.ElementText_KeyDown);
                this._elementTextBox.TextChanged -= new TextChangedEventHandler(this.ElementText_TextChanged);
            }
        }

        private void OnCalendarClosed(RoutedEventArgs e)
        {
            RoutedEventHandler calendarClosed = this.CalendarClosed;
            if (calendarClosed != null)
            {
                calendarClosed(this, e);
            }
        }

        private void OnCalendarOpened(RoutedEventArgs e)
        {
            RoutedEventHandler calendarOpened = this.CalendarOpened;
            if (calendarOpened != null)
            {
                calendarOpened(this, e);
            }
        }

        private void OnCalendarStyleChanged(Style oldValue)
        {
            if (((this.CalendarStyle != null) && (this._calendar != null)) && (this._calendar.Style == oldValue))
            {
                this._calendar.Style = this.CalendarStyle;
            }
        }

        private static void OnCalendarStylePropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            DatePicker picker = d as DatePicker;
            Style oldValue = (Style)e.OldValue;
            picker.OnCalendarStyleChanged(oldValue);
        }

        private void OnCustomFormatChanged(string oldValue)
        {
            this.BeginInvoke(() => this.OnCustomFormatChangedImpl(oldValue));
        }

        private void OnCustomFormatChangedImpl(string oldValue)
        {
            if (!string.IsNullOrEmpty(this.CustomFormat))
            {
                this.SelectedDateFormat = DatePickerFormat.Custom;
            }
            if (this._elementTextBox != null)
            {
                if (!this.SelectedDate.HasValue || string.IsNullOrEmpty(this._elementTextBox.Text))
                {
                    this.SetWaterMarkText();
                }
                else
                {
                    DateTime? selectedDate = this.SelectedDate;
                    DateTime? nullable = selectedDate.HasValue ? new DateTime?(selectedDate.GetValueOrDefault()) : this.ParseText(this._elementTextBox.Text);
                    if (nullable.HasValue)
                    {
                        string str = this.DateTimeToString(nullable.Value);
                        this.Text = str;
                    }
                }
            }
        }

        private static void OnCustomFormatPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            DatePicker picker = d as DatePicker;
            string oldValue = (string)e.OldValue;
            picker.OnCustomFormatChanged(oldValue);
        }

        protected virtual void OnDateValidationError(DatePickerDateValidationErrorEventArgs e)
        {
            EventHandler<DatePickerDateValidationErrorEventArgs> dateValidationError = this.DateValidationError;
            if (dateValidationError != null)
            {
                dateValidationError(this, e);
            }
        }

        private void OnDisplayDateChanged(DependencyPropertyChangedEventArgs e)
        {
            DateTime displayDate = this._calendar.DisplayDate;
            DateTime newValue = (DateTime)e.NewValue;
            if ((((displayDate.Year - newValue.Year) * 12) + (displayDate.Month - newValue.Month)) != 0)
            {
                this._calendar.DisplayDate = this.DisplayDate;
                if (DateTime.Compare(this._calendar.DisplayDate, this.DisplayDate) != 0)
                {
                    this.DisplayDate = this._calendar.DisplayDate;
                }
            }
        }

        private static void OnDisplayDateChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            ((DatePicker)d).OnDisplayDateChanged(e);
        }

        private void OnDisplayDateEndChanged(DependencyPropertyChangedEventArgs e)
        {
            this._calendar.DisplayDateEnd = this.DisplayDateEnd;
            if ((this._calendar.DisplayDateEnd.HasValue && this.DisplayDateEnd.HasValue) && (DateTime.Compare(this._calendar.DisplayDateEnd.Value, this.DisplayDateEnd.Value) != 0))
            {
                this.DisplayDateEnd = this._calendar.DisplayDateEnd;
            }
        }

        private static void OnDisplayDateEndChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            ((DatePicker)d).OnDisplayDateEndChanged(e);
        }

        private void OnDisplayDateStartChanged(DependencyPropertyChangedEventArgs e)
        {
            this._calendar.DisplayDateStart = this.DisplayDateStart;
            if ((this._calendar.DisplayDateStart.HasValue && this.DisplayDateStart.HasValue) && (DateTime.Compare(this._calendar.DisplayDateStart.Value, this.DisplayDateStart.Value) != 0))
            {
                this.DisplayDateStart = this._calendar.DisplayDateStart;
            }
        }

        private static void OnDisplayDateStartChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            ((DatePicker)d).OnDisplayDateStartChanged(e);
        }

        private void OnFirstDayOfWeekChanged(DayOfWeek oldValue)
        {
            if (this._calendar != null)
            {
                this._calendar.FirstDayOfWeek = this.FirstDayOfWeek;
            }
        }

        private static void OnFirstDayOfWeekPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            DatePicker picker = d as DatePicker;
            DayOfWeek oldValue = (DayOfWeek)e.OldValue;
            picker.OnFirstDayOfWeekChanged(oldValue);
        }

        private static void OnForceMouseOverPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            (d as DatePicker).ChangeVisualStateCommon(true);
        }

        private void OnIsDropDownOpenChanged(bool oldValue)
        {
            Action action = null;
            if (((this._elementPopup != null) && (this._elementPopup.Child != null)) && (this.IsDropDownOpen != oldValue))
            {
                if (this._calendar.DisplayMode != CalendarMode.Month)
                {
                    this._calendar.DisplayMode = CalendarMode.Month;
                }
                if (this.IsDropDownOpen)
                {
                    if (!this.IsReadOnly)
                    {
                        this._onOpenSelectedDate = this.SelectedDate;
                        this._calendar.Focus();
                        if (((Application.Current != null) ? (Application.Current.RootVisual as FrameworkElement) : null) != null)
                        {
                            if (base.ActualHeight == 0.0)
                            {
                                if (action == null)
                                {
                                    action = (Action)(() => this._elementPopup.IsOpen = true);
                                }
                                this.BeginInvoke(action);
                            }
                            else
                            {
                                this._elementPopup.IsOpen = true;
                            }
                        }
                        this.OnCalendarOpened(new RoutedEventArgs());
                    }
                }
                else
                {
                    this._elementPopup.IsOpen = false;
                    this.OnCalendarClosed(new RoutedEventArgs());
                    if (this._changed)
                    {
                        this.OnSelectionCommitted();
                    }
                    this._elementTextBox.Focus();
                }
            }
        }

        private static void OnIsDropDownOpenPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            DatePicker picker = d as DatePicker;
            bool oldValue = (bool)e.OldValue;
            picker.OnIsDropDownOpenChanged(oldValue);
        }

        private static void OnIsFocusedPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            (d as DatePicker).ChangeVisualStateFocus(true);
        }

        private static void OnIsMouseOverPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            DatePicker sender = d as DatePicker;
            if ((sender.IsMouseOverChanged != null) && sender._throwIsMouseOverChanged)
            {
                PropertyChangedEventArgs<bool> args = new PropertyChangedEventArgs<bool>
                {
                    OldValue = (bool)e.OldValue,
                    NewValue = (bool)e.NewValue
                };
                sender.IsMouseOverChanged(sender, args);
            }
            sender.ChangeVisualStateCommon(true);
        }

        private void OnIsReadOnlyChanged(bool oldValue)
        {
            this.HandleIsReadOnlyProperty();
        }

        private static void OnIsReadOnlyPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            DatePicker picker = d as DatePicker;
            bool oldValue = (bool)e.OldValue;
            picker.OnIsReadOnlyChanged(oldValue);
        }

        private void OnIsTodayHighlightedChanged(bool oldValue)
        {
            this._calendar.IsTodayHighlighted = this.IsTodayHighlighted;
        }

        private static void OnIsTodayHighlightedPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            DatePicker picker = d as DatePicker;
            bool oldValue = (bool)e.OldValue;
            picker.OnIsTodayHighlightedChanged(oldValue);
        }

        protected override void OnLostFocus(RoutedEventArgs e)
        {
            if ((((e.OriginalSource != null) && this.IsDropDownOpen) && ((this._elementButton != null) && !e.OriginalSource.Equals(this._elementTextBox))) && (!e.OriginalSource.Equals(this._elementButton) && !e.OriginalSource.Equals(this._calendar)))
            {
                this.ClosePopUp();
            }
            this.SetSelectedDate();
            base.OnLostFocus(e);
        }

        private void OnMaskChanged(string oldValue)
        {
            if (this._maskedBox != null)
            {
                this._maskedBox.Mask = this.Mask;
                if (!string.IsNullOrEmpty(this.Mask))
                {
                    this._maskedBox.PromptChar = this.Prompt[0];
                }
                if (this.SelectedDate.HasValue)
                {
                    this._maskedBox.Text = this.DateTimeToString(this.SelectedDate.Value);
                }
            }
        }

        private static void OnMaskPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            DatePicker picker = d as DatePicker;
            string oldValue = (string)e.OldValue;
            picker.OnMaskChanged(oldValue);
        }

        protected override void OnMouseWheel(System.Windows.Input.MouseWheelEventArgs e)
        {
            base.OnMouseWheel(e);
            if (this.IsFocused && ((!e.Handled && !this.IsReadOnly) && this.SelectedDate.HasValue))
            {
                DateTime time = this.SelectedDate.Value;
                DateTime? nullable = null;
                System.Globalization.Calendar calendar = new GregorianCalendar();
                try
                {
                    nullable = new DateTime?(calendar.AddDays(time, (e.Delta > 0) ? -1 : 1));
                }
                catch (ArgumentException)
                {
                }
                if (nullable.HasValue && this.IsValidDateSelection(nullable.Value))
                {
                    this.SelectedDate = nullable;
                    e.Handled = true;
                }
            }
        }

        private void OnPromptChanged(string oldValue)
        {
            this.OnMaskChanged(this.Mask);
        }

        private static void OnPromptPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            DatePicker picker = d as DatePicker;
            string oldValue = (string)e.OldValue;
            picker.OnPromptChanged(oldValue);
        }

        private void OnSelectedDateChanged(SelectionChangedEventArgs e)
        {
            SelectionChangedEventHandler selectedDateChanged = this.SelectedDateChanged;
            if (selectedDateChanged != null)
            {
                selectedDateChanged(this, e);
            }
            if (this.IsDropDownOpen)
            {
                this._changed = true;
            }
            else
            {
                this.OnSelectionCommitted();
            }
        }

        private void OnSelectedDateChanged(DependencyPropertyChangedEventArgs e)
        {
            Collection<DateTime> addedItems = new Collection<DateTime>();
            Collection<DateTime> removedItems = new Collection<DateTime>();
            DateTime? newValue = (DateTime?)e.NewValue;
            DateTime? oldValue = (DateTime?)e.OldValue;
            if (newValue.HasValue)
            {
                addedItems.Add(newValue.Value);
            }
            if (oldValue.HasValue)
            {
                removedItems.Add(oldValue.Value);
            }
            if (newValue != this._calendar.SelectedDate)
            {
                this._calendar.SelectedDate = newValue;
            }
            if (!this.SelectedDate.HasValue && !this.AllowNull)
            {
                this.SelectedDate = new DateTime?(DateTime.Today);
            }
            if (this.SelectedDate.HasValue)
            {
                DateTime day = this.SelectedDate.Value;
                this.BeginInvoke(delegate
                {
                    this._settingSelectedDate = true;
                    this.Text = this.DateTimeToString(day);
                    this._settingSelectedDate = false;
                    this.OnSelectedDateChanged(new SelectionChangedEventArgs(removedItems, addedItems));
                });
                if (((day.Month != this.DisplayDate.Month) || (day.Year != this.DisplayDate.Year)) && !this.IsDropDownOpen)
                {
                    this.DisplayDate = day;
                }
            }
            else
            {
                this._settingSelectedDate = true;
                this.SetWaterMarkText();
                this._settingSelectedDate = false;
                this.OnSelectedDateChanged(new SelectionChangedEventArgs(removedItems, addedItems));
            }
        }

        private static void OnSelectedDateChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            ((DatePicker)d).OnSelectedDateChanged(e);
        }

        private void OnSelectedDateFormatChanged(DatePickerFormat oldValue)
        {
            if (!IsValidSelectedDateFormat(this.SelectedDateFormat))
            {
                throw new ArgumentOutOfRangeException("SelectedDateFormat", "DatePickerFormat value is not valid.");
            }
            if (this._elementTextBox != null)
            {
                if (string.IsNullOrEmpty(this._elementTextBox.Text))
                {
                    this.SetWaterMarkText();
                }
                else
                {
                    DateTime? nullable = this.ParseText(this._elementTextBox.Text);
                    if (nullable.HasValue)
                    {
                        string str = this.DateTimeToString(nullable.Value);
                        this.Text = str;
                    }
                    else if (this.SelectedDate.HasValue)
                    {
                        string str2 = this.DateTimeToString(this.SelectedDate.Value);
                        this.Text = str2;
                    }
                    else
                    {
                        this.SetWaterMarkText();
                    }
                }
            }
        }

        private static void OnSelectedDateFormatPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            DatePicker picker = d as DatePicker;
            DatePickerFormat oldValue = (DatePickerFormat)e.OldValue;
            picker.OnSelectedDateFormatChanged(oldValue);
        }

        protected virtual void OnSelectionCommitted()
        {
            this._changed = false;
            if (this.SelectionCommitted != null)
            {
                PropertyChangedEventArgs<object> e = new PropertyChangedEventArgs<object>
                {
                    NewValue = this.SelectedDate
                };
                this.SelectionCommitted(this, e);
            }
        }

        private void OnTextChanged(string oldValue)
        {
            if (!this._typing)
            {
                if (this.Text == null)
                {
                    if (!this._settingSelectedDate)
                    {
                        base.SetValue(SelectedDateProperty, null);
                    }
                }
                else
                {
                    if (this._elementTextBox != null)
                    {
                        this._elementTextBox.Text = this.Text;
                    }
                    else
                    {
                        this._defaultText = this.Text;
                    }
                    if (!this._settingSelectedDate)
                    {
                        this.SetSelectedDate();
                    }
                }
            }
            else
            {
                this.SetWaterMarkText();
            }
        }

        private static void OnTextPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            DatePicker picker = d as DatePicker;
            string oldValue = (string)e.OldValue;
            picker.OnTextChanged(oldValue);
        }

        private void OnWatermarkChanged(object oldValue)
        {
            if (this._elementTextBox != null)
            {
                this.SetTextBoxValue(this._elementTextBox.Text);
            }
        }

        private static void OnWatermarkPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            DatePicker picker = d as DatePicker;
            object oldValue = e.OldValue;
            picker.OnWatermarkChanged(oldValue);
        }

        private void OutsidePopupCanvas_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
        {
            this.ClosePopUp();
        }

        private DateTime? ParseText(string text)
        {
            DateTime minValue = DateTime.MinValue;
            try
            {
                bool flag = false;
                if ((this.SelectedDateFormat == DatePickerFormat.Custom) && !string.IsNullOrEmpty(this.CustomFormat))
                {
                    flag = DateTime.TryParseExact(text, this.CustomFormat, TimeEditor.GetCurrentDateTimeFormat(this), DateTimeStyles.None, out minValue);
                }
                if (!flag)
                {
                    minValue = DateTime.Parse(text, TimeEditor.GetCurrentDateTimeFormat(this));
                }
                if (this.IsValidDateSelection(minValue))
                {
                    return new DateTime?(minValue);
                }
                DatePickerDateValidationErrorEventArgs e = new DatePickerDateValidationErrorEventArgs(new ArgumentOutOfRangeException("text", "SelectedDate value is not valid."), text);
                this.OnDateValidationError(e);
                if (e.ThrowException)
                {
                    throw e.Exception;
                }
            }
            catch (FormatException exception)
            {
                DatePickerDateValidationErrorEventArgs args2 = new DatePickerDateValidationErrorEventArgs(exception, text);
                this.OnDateValidationError(args2);
                if (args2.ThrowException)
                {
                    throw args2.Exception;
                }
            }
            return null;
        }

        private void SetCustomDefaultValues()
        {
            base.TabNavigation = KeyboardNavigationMode.Once;
            base.Loaded += (param0, param1) => this.ChangeVisualStateCommon(false);
            base.IsEnabledChanged += (s, a) => this.ChangeVisualStateCommon(true);
            base.MouseEnter += new MouseEventHandler(this.Control_MouseEnter);
            base.MouseLeave += new MouseEventHandler(this.Control_MouseLeave);
            base.IsTabStop = false;
            this.InitializeCalendar();
            this.FirstDayOfWeek = TimeEditor.GetCurrentDateTimeFormat(this).FirstDayOfWeek;
            this.DisplayDate = DateTime.Today;
        }

        private void SetPopUpPosition()
        {
            if (((this._calendar != null) && (Application.Current != null)) && ((Application.Current.Host != null) && (Application.Current.Host.Content != null)))
            {
                double actualHeight = Application.Current.Host.Content.ActualHeight;
                double actualWidth = Application.Current.Host.Content.ActualWidth;
                double num3 = this._calendar.ActualHeight;
                double num4 = base.ActualHeight;
                double num5 = this._calendar.ActualWidth;
                if (this._elementRoot != null)
                {
                    GeneralTransform transform = this._elementRoot.TransformToVisual(null);
                    if (transform != null)
                    {
                        Point point = new Point(0.0, 0.0);
                        Point point2 = new Point(1.0, 0.0);
                        Point point3 = new Point(0.0, 1.0);
                        Point point4 = transform.Transform(point);
                        Point point5 = transform.Transform(point2);
                        Point point6 = transform.Transform(point3);
                        double x = point4.X;
                        double y = point4.Y;
                        double num8 = x;
                        double num9 = y + num4;
                        if (actualHeight < (num9 + num3))
                        {
                            num9 = y - num3;
                        }
                        if (actualWidth < (num8 + num5))
                        {
                            num8 = actualWidth - num5;
                        }
                        if (base.FlowDirection == FlowDirection.RightToLeft)
                        {
                            if (actualWidth < (num8 + num5))
                            {
                                num8 = actualWidth - num5;
                            }
                        }
                        else if (num8 < 0.0)
                        {
                            num8 = 0.0;
                        }
                        this._elementPopup.HorizontalOffset = 0.0;
                        this._elementPopup.VerticalOffset = 0.0;
                        this._outsidePopupCanvas.Width = actualWidth;
                        this._outsidePopupCanvas.Height = actualHeight;
                        this._calendar.HorizontalAlignment = HorizontalAlignment.Left;
                        this._calendar.VerticalAlignment = VerticalAlignment.Top;
                        Canvas.SetLeft(this._calendar, num8 - x);
                        Canvas.SetTop(this._calendar, num9 - y);
                        Matrix identity = Matrix.Identity;
                        identity.M11 = point5.X - point4.X;
                        identity.M12 = point5.Y - point4.Y;
                        identity.M21 = point6.X - point4.X;
                        identity.M22 = point6.Y - point4.Y;
                        identity.OffsetX = point4.X;
                        identity.OffsetY = point4.Y;
                        MatrixTransform transform2 = new MatrixTransform();
                        InvertMatrix(ref identity);
                        transform2.Matrix = identity;
                        this._outsidePopupCanvas.RenderTransform = transform2;
                    }
                }
            }
        }

        private void SetSelectedDate()
        {
            if (this._elementTextBox != null)
            {
                if (!this.IsEmpty())
                {
                    string text = this._elementTextBox.Text;
                    if (!this.SelectedDate.HasValue || (this.DateTimeToString(this.SelectedDate.Value) != text))
                    {
                        DateTime? nullable = this.SetTextBoxValue(text);
                        if (!this.SelectedDate.Equals(nullable))
                        {
                            this.SelectedDate = nullable;
                        }
                    }
                }
                else if (!this.AllowNull)
                {
                    if (!this.SelectedDate.HasValue)
                    {
                        this.SelectedDate = new DateTime?(DateTime.Today);
                    }
                    this.SetTextBoxValue(this.DateTimeToString(this.SelectedDate.Value));
                }
                else if (this.SelectedDate.HasValue)
                {
                    this.SelectedDate = null;
                }
            }
            else
            {
                DateTime? nullable2 = this.SetTextBoxValue(this._defaultText);
                if (!this.SelectedDate.Equals(nullable2))
                {
                    this.SelectedDate = nullable2;
                }
            }
        }

        private DateTime? SetTextBoxValue(string s)
        {
            if (string.IsNullOrEmpty(s))
            {
                base.SetValue(TextProperty, s);
                if (!this.SelectedDate.HasValue)
                {
                    this.SetWaterMarkText();
                }
                return this.SelectedDate;
            }
            DateTime? nullable = this.ParseText(s);
            if (nullable.HasValue)
            {
                base.SetValue(TextProperty, s);
                return nullable;
            }
            if (this.SelectedDate.HasValue)
            {
                string str = this.DateTimeToString(this.SelectedDate.Value);
                base.SetValue(TextProperty, str);
                return this.SelectedDate;
            }
            this.SetWaterMarkText();
            return null;
        }

        private void SetWaterMarkText()
        {
            if (this._elementTextBox != null)
            {
                this._defaultText = this.Text = string.Empty;
                if ((this.Watermark == null) || string.IsNullOrEmpty(this.Watermark.ToString()))
                {
                    switch (this.SelectedDateFormat)
                    {
                        case DatePickerFormat.Long:
                            this._elementTextBox.Watermark = string.Format(CultureInfo.CurrentCulture, "<{0}>", new object[] { TimeEditor.GetCurrentDateTimeFormat(this).LongDatePattern.ToString() });
                            break;

                        case DatePickerFormat.Short:
                            this._elementTextBox.Watermark = string.Format(CultureInfo.CurrentCulture, "<{0}>", new object[] { TimeEditor.GetCurrentDateTimeFormat(this).ShortDatePattern.ToString() });
                            break;

                        case DatePickerFormat.Custom:
                            this._elementTextBox.Watermark = string.Format(CultureInfo.CurrentCulture, "<{0}>", new object[] { this.CustomFormat });
                            break;
                    }
                }
                else
                {
                    this._elementTextBox.Watermark = this.Watermark;
                }
                if (!this._typing)
                {
                    VisualStateHelper.GoToState(this._elementTextBox, "Watermarked", false);
                }
            }
        }

        private void TogglePopUp()
        {
            if (this.IsDropDownOpen)
            {
                this.ClosePopUp();
            }
            else if (!this.IsReadOnly)
            {
                this._calendar.CaptureMouse();
                this.SetSelectedDate();
                this.IsDropDownOpen = true;
                this._calendar.Focus();
            }
        }

        public override string ToString()
        {
            if (this.SelectedDate.HasValue)
            {
                return this.SelectedDate.Value.ToString(TimeEditor.GetCurrentDateTimeFormat(this));
            }
            return string.Empty;
        }

        // Properties
        public bool AllowNull
        {
            get { return (bool)GetValue(AllowNullProperty); }
            set { SetValue(AllowNullProperty, value); }
        }

        public CalendarBlackoutDatesCollection BlackoutDates { get; private set; }

        public Brush ButtonBackground
        {
            get { return (Brush)GetValue(ButtonBackgroundProperty); }
            set { SetValue(ButtonBackgroundProperty, value); }
        }

        public Brush ButtonForeground
        {
            get { return (Brush)GetValue(ButtonForegroundProperty); }
            set { SetValue(ButtonForegroundProperty, value); }
        }

        public Style CalendarStyle
        {
            get { return (Style)GetValue(CalendarStyleProperty); }
            set { SetValue(CalendarStyleProperty, value); }
        }

        public Brush CaretBrush
        {
            get { return (Brush)GetValue(CaretBrushProperty); }
            set { SetValue(CaretBrushProperty, value); }
        }

        public CornerRadius CornerRadius
        {
            get { return (CornerRadius)GetValue(CornerRadiusProperty); }
            set { SetValue(CornerRadiusProperty, value); }
        }

        public string CustomFormat
        {
            get { return (string)GetValue(CustomFormatProperty); }
            set { SetValue(CustomFormatProperty, value); }
        }

        public Visibility DisabledCuesVisibility
        {
            get { return (Visibility)GetValue(DisabledCuesVisibilityProperty); }
            set { SetValue(DisabledCuesVisibilityProperty, value); }
        }

        [TypeConverter(typeof(DateTimeTypeConverter))]
        public DateTime DisplayDate
        {
            get { return (DateTime)GetValue(DisplayDateProperty); }
            set { SetValue(DisplayDateProperty, value); }
        }

        [TypeConverter(typeof(DateTimeTypeConverter))]
        public DateTime? DisplayDateEnd
        {
            get { return (DateTime?)GetValue(DisplayDateEndProperty); }
            set { SetValue(DisplayDateEndProperty, value); }
        }

        [TypeConverter(typeof(DateTimeTypeConverter))]
        public DateTime? DisplayDateStart
        {
            get { return (DateTime?)GetValue(DisplayDateStartProperty); }
            set { SetValue(DisplayDateStartProperty, value); }
        }

        public DayOfWeek FirstDayOfWeek
        {
            get { return (DayOfWeek)GetValue(FirstDayOfWeekProperty); }
            set { SetValue(FirstDayOfWeekProperty, value); }
        }

        public Brush FocusBrush
        {
            get { return (Brush)GetValue(FocusBrushProperty); }
            set { SetValue(FocusBrushProperty, value); }
        }

        public Visibility FocusCuesVisibility
        {
            get { return (Visibility)GetValue(FocusCuesVisibilityProperty); }
            set { SetValue(FocusCuesVisibilityProperty, value); }
        }

        internal bool ForceMouseOver
        {
            get { return (bool)GetValue(ForceMouseOverProperty); }
            set { SetValue(ForceMouseOverProperty, value); }
        }

        public bool IsDropDownOpen
        {
            get { return (bool)GetValue(IsDropDownOpenProperty); }
            set { SetValue(IsDropDownOpenProperty, value); }
        }

        public bool IsFocused
        {
            get { return (bool)GetValue(IsFocusedProperty); }
            internal set { SetValue(IsFocusedProperty, value); }
        }

        public bool IsMouseOver
        {
            get { return (bool)GetValue(IsMouseOverProperty); }
            internal set { SetValue(IsMouseOverProperty, value); }
        }

        public bool IsReadOnly
        {
            get { return (bool)GetValue(IsReadOnlyProperty); }
            set { SetValue(IsReadOnlyProperty, value); }
        }

        public bool IsTodayHighlighted
        {
            get { return (bool)GetValue(IsTodayHighlightedProperty); }
            set { SetValue(IsTodayHighlightedProperty, value); }
        }

        public string Mask
        {
            get { return (string)GetValue(MaskProperty); }
            set { SetValue(MaskProperty, value); }
        }

        public Brush MouseOverBrush
        {
            get { return (Brush)GetValue(MouseOverBrushProperty); }
            set { SetValue(MouseOverBrushProperty, value); }
        }

        public Brush PressedBrush
        {
            get { return (Brush)GetValue(PressedBrushProperty); }
            set { SetValue(PressedBrushProperty, value); }
        }

        public string Prompt
        {
            get { return (string)GetValue(PromptProperty); }
            set { SetValue(PromptProperty, value); }
        }

        [TypeConverter(typeof(DateTimeTypeConverter))]
        public DateTime? SelectedDate
        {
            get { return (DateTime?)GetValue(SelectedDateProperty); }
            set { SetValue(SelectedDateProperty, value); }
        }

        public DatePickerFormat SelectedDateFormat
        {
            get { return (DatePickerFormat)GetValue(SelectedDateFormatProperty); }
            set
            {
                SetValue(SelectedDateFormatProperty, value);
            }
        }

        public Brush SelectionBackground
        {
            get { return (Brush)GetValue(SelectionBackgroundProperty); }
            set { SetValue(SelectionBackgroundProperty, value); }
        }

        public Brush SelectionForeground
        {
            get { return (Brush)GetValue(SelectionForegroundProperty); }
            set { SetValue(SelectionForegroundProperty, value); }
        }

        public string Text
        {
            get { return (string)GetValue(TextProperty); }
            set { SetValue(TextProperty, value); }
        }

        public Style ValidationDecoratorStyle
        {
            get { return (Style)GetValue(ValidationDecoratorStyleProperty); }
            set { SetValue(ValidationDecoratorStyleProperty, value); }
        }

        public object Watermark
        {
            get { return GetValue(WatermarkProperty); }
            set { SetValue(WatermarkProperty, value); }
        }
    }
}
